using System;
using System.CodeDom;
using System.IO;
using System.Reflection;
using System.Text;
using UnityEditor;
using UnityEngine;

namespace IcecreamView.Editor
{
    public static class IceCreamCodeUtils
    {

        public const string Templete = @"using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using IcecreamView;

#NamespaceStart

    public class #ScriptName : #Abstract
    {
        public override void OnInitView(){}

        public override void OnOpenView(Dictionary<string,IC_ViewData> parameters){}

        public override void OnCloseView(){}

        public override void OnDestroyView(){}
    }
#NamespaceEnd
";

        public static void CreateCode(SerializedObject target)
        {
            if (target.targetObject == null || string.IsNullOrEmpty(target.targetObject.name))
            {
                return;
            }

            // CodeCompileUnit unit = new CodeCompileUnit();
            // //设置命名空间（这个是指要生成的类的空间）
            // CodeNamespace myNamespace = new CodeNamespace("Joh.Test");
            // //导入必要的命名空间引用
            // myNamespace.Imports.Add(new CodeNamespaceImport("System"));
            // myNamespace.Imports.Add(new CodeNamespaceImport("UnityEngine"));
            // //Code:代码体
            // CodeTypeDeclaration myClass = new CodeTypeDeclaration(className);

            string className = string.IsNullOrEmpty(GlobalInstance.NameSpacePath) ? target.targetObject.name : GlobalInstance.NameSpacePath + "." + target.targetObject.name;
            string objPath   = GetGameObjectPath(((IC_ModuleConnector) target.targetObject).transform);
            WriteFile("Temp", "ICE_ACTION.tmp", StringToArrayByteUtf8(className + "#" + objPath));

            string path     = $"Assets/{GlobalInstance.FilePath ?? "Scripts/View"}";
            string fileName = $"{target.targetObject.name.Replace(" ", "")}.cs";
            if (!File.Exists(path + "/" + fileName))
            {
                //创建代码
                string fileContent = Templete;
                if (string.IsNullOrEmpty(GlobalInstance.NameSpacePath) == false)
                {
                    fileContent = fileContent.Replace("#NamespaceStart", $"namespace {GlobalInstance.NameSpacePath}" + "{");
                    fileContent = fileContent.Replace("#NamespaceEnd",   "}");
                }
                else
                {
                    fileContent = fileContent.Replace("#NamespaceStart", "");
                    fileContent = fileContent.Replace("#NamespaceEnd",   "");
                }

                fileContent = fileContent.Replace("#Abstract",   GlobalInstance.AbstractClass ?? "IC_AbstractModule");
                fileContent = fileContent.Replace("#ScriptName", target.targetObject.name);
                WriteFile(path, fileName, StringToArrayByteUtf8(fileContent));
                Debug.Log("构建UI代码完成：" + path + "/" + fileName);
                AssetDatabase.Refresh();
            }
            else
            {
                // Debug.Log("已存在相同文件名：" + path + "/" + fileName);
                BindComponent();
            }
        }

        [UnityEditor.Callbacks.DidReloadScripts]
        public static void BindComponent()
        {
            if (File.Exists("Temp/ICE_ACTION.tmp") == false)
            {
                return;
            }

            string fileContent = ReadFile("Temp", "ICE_ACTION.tmp");
            File.Delete("Temp/ICE_ACTION.tmp");
            string className = fileContent.Substring(0, fileContent.IndexOf("#", StringComparison.Ordinal));
            string objPath   = fileContent.Substring(fileContent.IndexOf("#", StringComparison.Ordinal) + 1);
            var    assembly  = Assembly.Load(GlobalInstance.AssemblyName);
            if (assembly == null)
            {
                Debug.LogError("加载失败：" + GlobalInstance.AssemblyName);
                return;
            }

            Type t   = assembly.GetType(className);
            var  obj = GameObject.Find(objPath);
            if (t != null)
            {
                if (!obj.GetComponent(t))
                {
                    obj.gameObject.AddComponent(t);
                }

                var prefabPath = "Assets/" + GlobalInstance.PrefabsPath + "/" + obj.name + ".prefab";
                if (Directory.Exists("Assets/" + GlobalInstance.PrefabsPath) == false)
                {
                    Directory.CreateDirectory("Assets/" + GlobalInstance.PrefabsPath);
                }

                if (File.Exists(prefabPath))
                {
                    //保存修改到预制体
                    PrefabUtility.ApplyPrefabInstance(obj, InteractionMode.AutomatedAction);
                }
                else
                {
                    //创建预制体
                    PrefabUtility.SaveAsPrefabAssetAndConnect(obj, prefabPath, InteractionMode.AutomatedAction);
                }

                Debug.Log("构建UI预制体完成：" + prefabPath);
                AssetDatabase.Refresh();
            }
        }

        private static string GetGameObjectPath(Transform obj)
        {
            Transform selectChild = obj;
            string    result      = selectChild.name;
            if (selectChild != null)
            {
                while (selectChild.parent != null)
                {
                    selectChild = selectChild.parent;
                    result      = string.Format("{0}/{1}", selectChild.name, result);
                }
            }

            return result;
            // Debug.Log(string.Format("The gameobject:{0}'s path has been copied to the clipboard!", obj.name));
        }


        private static IC_GlobalSetting _globalInstance;

        public static IC_GlobalSetting GlobalInstance
        {
            get
            {
                if (_globalInstance == null)
                {
                    _globalInstance = Resources.Load<IC_GlobalSetting>("IceCreamGlobalSettings");
#if UNITY_EDITOR
                    if (_globalInstance == null)
                    {
                        _globalInstance = ScriptableObject.CreateInstance<IC_GlobalSetting>();
                        // 自定义资源保存路径
                        string path = "Assets/Resources";
                        //如果项目总不包含该路径，创建一个
                        if (!Directory.Exists(path))
                        {
                            Directory.CreateDirectory(path);
                        }

                        AssetDatabase.CreateAsset(_globalInstance, path + "/IceCreamGlobalSettings.asset");
                        AssetDatabase.Refresh();
                        _globalInstance = Resources.Load<IC_GlobalSetting>("IceCreamGlobalSettings");
                    }
#endif
                }

                return _globalInstance;
            }
        }

        public static void WriteFile(string path, string fileName, byte[] content)
        {
            CreateDirectory(path);
            var        fullName = path + "/" + fileName;
            FileStream fs       = new FileStream(fullName, FileMode.Create, FileAccess.Write, FileShare.None, 4096, FileOptions.None);
            fs.Write(content, 0, content.Length);
            fs.Close();
        }

        public static void CreateDirectory(string path)
        {
            if (!(Directory.Exists(path) || File.Exists(path)))
            {
                Directory.CreateDirectory(path);
            }
        }

        public static string ReadFile(string path, string fileName)
        {
            var fullName = path + "/" + fileName;
            if (Directory.Exists(path) || File.Exists(path))
            {
                FileStream fs    = new FileStream(fullName, FileMode.Open, FileAccess.Read, FileShare.None, 4096, FileOptions.None);
                byte[]     bytes = new byte[fs.Length];
                fs.Read(bytes, 0, bytes.Length);
                fs.Close();
                return ArrayByteUtf8ToString(bytes);
            }

            return null;
        }

        public static byte[] StringToArrayByteUtf8(string value) { return Encoding.UTF8.GetBytes(value); }
        public static string ArrayByteUtf8ToString(byte[] bytes) { return Encoding.UTF8.GetString(bytes); }

    }
}